using System;
using System.Collections.Generic;
using System.Text;

using SlimDX;
using SlimDX.Direct3D9;
using System.Collections;

using miciv;
using miciv.Rendering;
using miciv.Geometry;
using micivCore.Components;

namespace micivCore.Data
{
    public class MapTileRenderable : RenderableBase, IDiffuse, IAlbedoTexture, IMaskTexture
    {
        public struct Vertex
        {
            public Vector3 Position;
            public Color4 Color;
            public Vector2 UV;
        }

        protected MapTileGeometryDefinition m_geometryDefinition;
        public MapTileGeometryDefinition GeometryDefinition
        {
            get
            {
                return this.m_geometryDefinition;
            }
            set
            {
                if (value != this.m_geometryDefinition)
                {
                    this.m_geometryDefinition = value;
                    this.Albedo = this.m_geometryDefinition.GetSemantic<TextureManager.ManagedTexture>("AlbedoTexture");
                    this.Diffuse = this.m_geometryDefinition.GetSemantic<Color4>("DiffuseColor");
                    this.IsDirty = true;
                }
            }
        }

        protected bool m_bDirty;
        public bool IsDirty
        {
            get
            {
                return this.m_bDirty;
            }
            set
            {
                this.m_bDirty = value;
            }
        }

        protected Vector2 m_f2Position;
        public Vector2 Position
        {
            get
            {
                return this.m_f2Position;
            }
            set
            {
                if (value != this.m_f2Position)
                {
                    this.m_f2Position = value;
                    this.IsDirty = true;
                }
            }
        }

        protected Vector2 m_f2Size;
        public Vector2 Size
        {
            get
            {
                return this.m_f2Size;
            }
            set
            {
                if (value != this.m_f2Size)
                {
                    this.m_f2Size = value;
                    this.IsDirty = true;
                }
            }
        }

        protected bool m_bIsVisible;
        public bool IsVisible
        {
            get
            {
                return this.m_bIsVisible;
            }
            set
            {
                this.m_bIsVisible = value;
            }
        }

        protected MapTileGeometryDefinition _geometryDefinition;
        protected Vertex[] m_vertices;
        protected TextureManager.ManagedTexture m_albedoTexture;
        protected TextureManager.ManagedTexture m_maskTexture;
        protected Color4 m_f4Diffuse;
        protected int m_sVertexCount;
        protected Matrix m_matScale;
        protected MapTile m_mapTile;

        public MapTileRenderable(MapTile _mapTile, MapTileGeometryDefinition _geometryDefinition)
            : base(_geometryDefinition.CoreContext)
        {
            this.GeometryDefinition = _geometryDefinition;
            this.m_mapTile = _mapTile;
            this.Mask = this.m_mapTile.MapProto.MaskTexture;
            this.Position = new Vector2(0.0f, 0.0f);
            this.m_matScale = Matrix.Identity;
            this.IsVisible = false;
        }

        #region IRenderable Membres

        override public IRenderer Renderer
        {
            get
            {
                return this.GeometryDefinition.Renderer;
            }
        }

        override public void UpdateData(float _deltaTime)
        {
            base.UpdateData(_deltaTime);
            if ((false != this.IsDirty) && (null != this.Renderer))
            {
                Matrix.Translation(this.Position.X, this.Position.Y, 0.0f, out this.m_matWorld);
                // definition item is providing its own geometry data and we know, by design, that geometry is a normalized square (1x1).
                // therefore we have to applay a scale to that geometry in order to render it at the expeced original size.
                Matrix.Scaling(this.Size.X, this.Size.Y, 1.0f, out this.m_matScale);
                Matrix.Multiply(ref this.m_matScale, ref this.m_matWorld, out this.m_matWorld);
                this.IsDirty = false;
            }
        }

        override public List<IVertexFeeder> VertexFeeders
        {
            get
            {
                if ((null != this.m_vertexFeeders) && (0 < this.m_vertexFeeders.Count))
                {
                    return this.m_vertexFeeders;
                }
                return this.GeometryDefinition.VertexFeeders;
            }
        }

        public void Release()
        {
            if (null != this.m_vertexFeeders)
            {
                this.Renderer.ReleaseFeeders(this.m_vertexFeeders);
            }
        }

        #endregion

        #region IAlbedoTexture Membres

        public TextureManager.ManagedTexture Albedo
        {
            get
            {
                return this.m_albedoTexture;
            }
            set
            {
                this.m_albedoTexture = value;
            }
        }

        #endregion

        #region IMaskTexture Membres

        public TextureManager.ManagedTexture Mask
        {
            get
            {
                return this.m_maskTexture;
            }
            set
            {
                if (value != this.m_maskTexture)
                {
                    this.m_maskTexture = value;
                    ImageInformation imgInfo = this.m_maskTexture.Info;
                    this.Size = new Vector2(imgInfo.Width, imgInfo.Height);
                    //this.IsDirty = true;
                }
            }
        }

        #endregion

        #region IDiffuse Membres

        public Color4 Diffuse
        {
            get
            {
                return this.m_f4Diffuse;
            }
            set
            {
                this.m_f4Diffuse = value;
            }
        }

        #endregion
    }
}
